import struct
from dataclasses import dataclass
from typing import List, Dict, Union

@dataclass
class Sniffer:
    def sniff(self, header: bytes) -> bool:
        pass

@dataclass
class PrefixSniffer(Sniffer):
    prefix: bytes

    def sniff(self, header: bytes) -> bool:
        return header.startswith(self.prefix)

@dataclass
class M4ASniffer(Sniffer):
    def sniff(self, header: bytes) -> bool:
        box = read_mpeg4_ftyp_box(header)
        if box is None:
            return False
        return box['major_brand'] == b'M4A ' or b'M4A ' in box['compatible_brands']

@dataclass
class MPEG4Sniffer(Sniffer):
    def sniff(self, header: bytes) -> bool:
        return read_mpeg4_ftyp_box(header) is not None

def read_mpeg4_ftyp_box(header: bytes) -> dict:
    if len(header) < 8 or header[4:8] != b'ftyp':
        return None
    size = struct.unpack('>I', header[0:4])[0]
    if size < 16 or size % 4 != 0:
        return None
    box = {
        'major_brand': header[8:12],
        'minor_version': struct.unpack('>I', header[12:16])[0],
        'compatible_brands': [header[i:i+4] for i in range(16, size, 4)]
    }
    return box

audio_extensions = {
    ".mp3": PrefixSniffer(b'ID3'),
    ".ogg": PrefixSniffer(b'OggS'),
    ".wav": PrefixSniffer(b'RIFF'),
    ".wma": PrefixSniffer(b'\x30\x26\xb2\x75\x8e\x66\xcf\x11\xa6\xd9\x00\xaa\x00\x62\xce\x6c'),
    ".m4a": M4ASniffer(),
    ".mp4": MPEG4Sniffer(),
    ".flac": PrefixSniffer(b'fLaC'),
    ".dff": PrefixSniffer(b'FRM8'),
}

def audio_extension(header: bytes) -> tuple[str, bool]:
    for ext, sniffer in audio_extensions.items():
        if sniffer.sniff(header):
            return ext, True
    return "", False

def audio_extension_with_fallback(header: bytes, fallback: str) -> str:
    ext, ok = audio_extension(header)
    if not ok:
        return fallback
    return ext
